﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using KZ.Exception;
using KZ.Lottery.Entities;
using KZ.Lottery.Resources;
using KZ.Utilities;

namespace KZ.Lottery.DAL
{
    public class RuleDAL
    {
        private static Entities.Rule CreateRuleFromReader(SqlDataReader reader)
        {
            Entities.Rule rule = new Entities.Rule
            {
                RuleID = Utility.StringParse(reader[RuleColumns.RuleID.ToString()]),
                RuleName = Utility.StringParse(reader[RuleColumns.RuleName.ToString()]),
                Description = Utility.StringParse(reader[RuleColumns.Description.ToString()]),
                IsActived = Utility.BoolParse(reader[RuleColumns.IsActived.ToString()]),
                IsDeleted = Utility.BoolParse(reader[RuleColumns.IsDeleted.ToString()]),
                CreatedDate = Utility.DateTimeParse(reader[RuleColumns.CreatedDate.ToString()]),
            };

            return rule;
        }

        public static Entities.Rule GetRule(string ruleID)
        {
            try
            {
                Entities.Rule rule = new Entities.Rule();

                DataAccessHelper.SqlCmd.Parameters.Add("RuleID", SqlDbType.NVarChar).Value = ruleID;
                using (SqlDataReader reader = DataAccessHelper.ExecuteQuery(CommandType.StoredProcedure, KZ_StoreName.RuleGetByID))
                {
                    if (reader.Read())
                    {
                        rule = CreateRuleFromReader(reader);
                    }
                }

                rule.RuleDetailList = RuleDetailDAL.GetRuleDetailList(rule.RuleID);

                return rule;
            }
            catch (SqlException ex)
            {
                Log.LogEx("GetRule", ex);
                throw new DataAccessException(KZ_Message.BLM_ERR_RULE_GET);
            }
        }

        public static List<Entities.Rule> GetRuleList()
        {
            try
            {
                List<Entities.Rule> ruleList = new List<Entities.Rule>();

                using (SqlDataReader reader = DataAccessHelper.ExecuteQuery(CommandType.StoredProcedure, KZ_StoreName.RuleGetList))
                {
                    while (reader.Read())
                    {
                        ruleList.Add(CreateRuleFromReader(reader));
                    }
                }

                return ruleList;
            }
            catch (SqlException ex)
            {
                Log.LogEx("GetRuleList", ex);
                throw new DataAccessException(KZ_Message.BLM_ERR_RULE_GET);
            }
        }

        public static bool DeleteRule(string ruleID)
        {
            try
            {
                DataAccessHelper.SqlCmd.Parameters.Add("RuleID", SqlDbType.VarChar).Value = ruleID;
                if (DataAccessHelper.ExecuteNonQuery(CommandType.StoredProcedure, KZ_StoreName.RuleDelete) > 0)
                {
                    return true;
                }

                throw new DataAccessException(KZ_Message.BLM_ERR_RULE_DELETE);
            }
            catch (SqlException ex)
            {
                Log.LogEx("DeleteRule", ex);
                throw new DataAccessException(KZ_Message.BLM_ERR_RULE_DELETE);
            }
        }

        public static bool UpdateRuleIsActived(string ruleID, bool isActived)
        {
            try
            {
                DataAccessHelper.SqlCmd.Parameters.Add("RuleID", SqlDbType.VarChar).Value = ruleID;
                DataAccessHelper.SqlCmd.Parameters.Add("IsActived", SqlDbType.Bit).Value = isActived;
                if (DataAccessHelper.ExecuteNonQuery(CommandType.StoredProcedure, KZ_StoreName.RuleUpdateIsActived) > 0)
                {
                    return true;
                }

                throw new DataAccessException(KZ_Message.BLM_ERR_RULE_UPDATE);
            }
            catch (SqlException ex)
            {
                Log.LogEx("UpdateRuleIsActived", ex);
                throw new DataAccessException(KZ_Message.BLM_ERR_RULE_UPDATE);
            }
        }

        public bool InsertRuleAndDetail(Entities.Rule rule)
        {
            try
            {
                List<Group> groupList = GroupDAL.GetGroupList();
                SettingValue settingValue = SettingValueDAL.GetSettingValueFirstDay();

                DataAccessHelper.BeginTransaction(IsolationLevel.Serializable);

                rule.RuleID = Guid.NewGuid().ToString();
                InsertRule(rule);

                RuleDetailDAL ruleDetailDAL = new RuleDetailDAL();
                RuleDetailChannelDAL ruleDetailChannelDAL = new RuleDetailChannelDAL();
                RuleDetailGroupDAL ruleDetailGroupDAL = new RuleDetailGroupDAL();
                foreach (RuleDetail item in rule.RuleDetailList)
                {
                    item.RuleID = rule.RuleID;
                    item.RuleDetailID = Guid.NewGuid().ToString();
                    ruleDetailDAL.InsertRuleDetail(item);

                    foreach (RuleDetailChannel subItem in item.RuleDetailChannelList)
                    {
                        subItem.RuleDetailID = item.RuleDetailID;
                        subItem.RuleID = rule.RuleID;
                        ruleDetailChannelDAL.InsertRuleDetailChannel(subItem);
                    }

                    foreach (Group g in groupList)
                    {
                        RuleDetailGroup ruleDetailGroup = new RuleDetailGroup
                        {
                            RuleDetailID = item.RuleDetailID,
                            GroupID = g.GroupID,
                            HeadDay = settingValue.Day,
                            TailDay = settingValue.Day,
                            FirstDayAmount = settingValue.Value
                        };
                        ruleDetailGroupDAL.InsertRuleDetailGroup(ruleDetailGroup);
                    }
                }

                DataAccessHelper.CommitTransaction();

                return true;
            }
            catch (DataAccessException)
            {
                DataAccessHelper.RollbackTransaction();
                throw;
            }
        }

        public bool UpdateRuleAndDetail(Entities.Rule rule)
        {
            try
            {
                List<Group> groupList = GroupDAL.GetGroupList();
                SettingValue settingValue = SettingValueDAL.GetSettingValueFirstDay();

                DataAccessHelper.BeginTransaction(IsolationLevel.Serializable);

                UpdateRule(rule);

                RuleDetailDAL ruleDetailDAL = new RuleDetailDAL();
                RuleDetailChannelDAL ruleDetailChannelDAL = new RuleDetailChannelDAL();
                RuleDetailChannelDAL.DeleteRuleDetailChannel(rule.RuleID);

                string ruleDetailID = String.Empty;
                foreach (RuleDetail item in rule.RuleDetailList)
                {
                    item.RuleID = rule.RuleID;
                    if (String.IsNullOrEmpty(item.RuleDetailID))
                    {
                        item.RuleDetailID = Guid.NewGuid().ToString();
                        ruleDetailDAL.InsertRuleDetail(item);
                    }
                    else
                    {
                        ruleDetailDAL.UpdateRuleDetail(item);
                    }

                    ruleDetailID += "'" + item.RuleDetailID + "',";

                    foreach (RuleDetailChannel subItem in item.RuleDetailChannelList)
                    {
                        subItem.RuleDetailID = item.RuleDetailID;
                        subItem.RuleID = rule.RuleID;
                        ruleDetailChannelDAL.InsertRuleDetailChannel(subItem);
                    }
                }
                if (ruleDetailID.EndsWith(",")) { ruleDetailID = ruleDetailID.Remove(ruleDetailID.Length - 1); }

                RuleDetailDAL.DeleteRuleDetail(rule.RuleID, ruleDetailID);

                DataAccessHelper.CommitTransaction();

                return true;
            }
            catch (DataAccessException)
            {
                DataAccessHelper.RollbackTransaction();
                throw;
            }
        }

        private bool InsertRule(Entities.Rule rule)
        {
            try
            {
                DataAccessHelper.SqlCmd.Parameters.Add("RuleID", SqlDbType.NVarChar).Value = rule.RuleID;
                DataAccessHelper.SqlCmd.Parameters.Add("RuleName", SqlDbType.NVarChar).Value = rule.RuleName;
                DataAccessHelper.SqlCmd.Parameters.Add("Description", SqlDbType.NVarChar).Value = rule.Description;
                DataAccessHelper.SqlCmd.Parameters.Add("IsActived", SqlDbType.Bit).Value = rule.IsActived;
                if (DataAccessHelper.ExecuteNonQueryWithTransaction(CommandType.StoredProcedure, KZ_StoreName.RuleInsert) > 0)
                {
                    return true;
                }

                throw new DataAccessException(KZ_Message.BLM_ERR_RULE_INSERT);
            }
            catch (SqlException ex)
            {
                Log.LogEx("InsertRule", ex);
                throw new DataAccessException(KZ_Message.BLM_ERR_RULE_INSERT);
            }
        }

        private bool UpdateRule(Entities.Rule rule)
        {
            try
            {
                DataAccessHelper.SqlCmd.Parameters.Add("RuleID", SqlDbType.NVarChar).Value = rule.RuleID;
                DataAccessHelper.SqlCmd.Parameters.Add("RuleName", SqlDbType.NVarChar).Value = rule.RuleName;
                DataAccessHelper.SqlCmd.Parameters.Add("Description", SqlDbType.NVarChar).Value = rule.Description;
                DataAccessHelper.SqlCmd.Parameters.Add("IsActived", SqlDbType.Bit).Value = rule.IsActived;
                if (DataAccessHelper.ExecuteNonQueryWithTransaction(CommandType.StoredProcedure, KZ_StoreName.RuleUpdate) > 0)
                {
                    return true;
                }

                throw new DataAccessException(KZ_Message.BLM_ERR_RULE_UPDATE);
            }
            catch (SqlException ex)
            {
                Log.LogEx("UpdateRule", ex);
                throw new DataAccessException(KZ_Message.BLM_ERR_RULE_UPDATE);
            }
        }
    }
}